import { add, assign, clone, eachTree, findTree, isObject, sum, toArrayTree } from 'xe-utils'
import {
  formatDicTable,
  formatOptions,
  formatRowComponents,
  getBusinessBind,
  getFormatOptions,
  getNotEmpty,
  wfStatusTypes
} from '@/utils/custom'
import type {
  VxeTableDefines,
  VxeColumnPropTypes,
  VxeGridProps,
  VxeTablePropTypes
} from 'vxe-table'
import type {
  BusinessUIAction,
  BusinessUIColumnType,
  BusinessUIFormType,
  BusinessUIQueryColumnType,
  BusinessUITableType,
  DicType,
  TabHeadType
} from '@/types/custom'
import { swapArray, toNameCapitalize } from '@/utils'
import { Local } from '@/utils/storage'
import { onComponentServerFetch, onInitApiData } from '@/views/components/form/libs'
import { themeConfig } from '@/storage'
import { i18n } from '@/i18n'
// @ts-ignore 不校验 i18n.global 规则冲突 (Vue: Type instantiation is excessively deep and possibly infinite.)
const { t } = i18n.global

interface TabHeadData {
  tabHead: TabHeadType[]
  items: any[]
}

interface DataInterface {
  data?: TabHeadData
  uiForm?: BusinessUIFormType
  dicTable?: DicType[]
  uiTable: BusinessUITableType
  uiActions?: BusinessUIAction[]
  params?: TypedAny
  disabled?: boolean
}

/**
 * 可以行内编辑的组件
 */
export const edit_render_components = [
  'el-select',
  'el-date-picker',
  'el-switch',
  'el-input-number',
  'el-input',
  'el-tree-select'
]

/**
 * 格式化多级表配置
 * @param option
 */
export const initFormatTabHead = async (option: DataInterface) => {
  const { data } = option
  if (!data) return { cols: [], items: [] }
  const heads = toArrayTree(data.tabHead, { parentKey: 'p_id' })
  const cols = await initFormatColumns(option)
  let currentCol: any = null
  const swap: { A: number; B: number }[] = []
  const hideFields: string[] = []
  eachTree(heads, (item) => {
    if (!item.p_id) {
      // const column_name = item.column_name[0]
      const column_name = item.column_data
      hideFields.push(...item.column_name)
      const col = cols.find((f) => column_name === f.field)
      if (col) currentCol = col
      if (item.column_change) {
        swap.push({
          A: cols.findIndex((f) => f.field === item.column_change),
          B: cols.findIndex((f) => f.field === column_name)
        })
      }
    }

    if (currentCol) assign(item, clone(currentCol, true))

    // item.field = !item.p_id ? item.field : `${item.field}_${index}`
    item.field = !item.p_id ? item.field : item.id
    item.title = item.name

    // 数据
    if (!item.children.length) {
      const ls = data.items.filter((f) => {
        const value = f[item.column_data]
        if (isObject(value)) {
          return value !== undefined
        } else {
          return f[item.column_id] === item.id
        }
      })
      ls.forEach((v) => {
        const value = v[item.column_data]
        if (isObject(value)) {
          // @ts-ignore
          v[item.field] = value[item.field]
          v[`${item.field}_name`] = item.title
        } else {
          v[item.field] = value
        }
      })
    }
  })

  // 加入列合计
  eachTree(heads, (item) => {
    if (item.children.length) {
      const first = item.children[0]
      if (!first.children.length) {
        const option = clone(first, true)
        option.name = option.title = '小计'
        option.params.set_json_parse.props.width = '90'
        option.width = '90'
        option.field = item.field + '_total'
        const keys = item.children.map((v) => v.field)
        data.items.forEach((v) => {
          v[option.field] = sum(keys.map((k) => v[k] || 0))
        })
        item.children.push(option)
      }
    }
  })
  // 交换位置
  swap.forEach((v) => {
    swapArray(cols, v.A, v.B)
  })
  // 将生成的多级列，替换现有的列
  heads.forEach((item) => {
    // const column_name = item.column_name[0]
    const column_name = item.column_data
    const index = cols.findIndex((f) => f.field === column_name)
    if (index >= 0) cols.splice(index, 1, item)
  })
  return {
    cols: cols.filter((f) => !hideFields.includes(f.field)),
    items: data.items
  }
}

/**
 * 获取字典下拉
 * @param form
 * @param dicTable
 */
export const getDicOptions = (form: BusinessUIQueryColumnType, dicTable: DicType[]) => {
  const list: SelectOptionType[] = []
  dicTable
    .filter((f) => f.column_name === form.field)
    .forEach((v) => {
      list.push({
        value: v.value_text,
        label: v.display_text
      })
    })
  return list
}

/**
 * element-plus 转 vxe-table组件
 * 表格行内编辑时转换（仅支持部分组件）
 */
export const elToVxeComponent = (key: string) => {
  const options: TypedString = {
    'el-select': 'vxe-select',
    'el-input': 'vxe-input',
    'el-tree-select': 'vxe-tree-select',
    'el-date-picker': 'vxe-date-picker',
    'el-input-number': 'vxe-number-input'
  }
  return options[key] || key
}

/**
 * 格式化表列
 * @param option
 */
export const initFormatColumns = async (option: DataInterface) => {
  const { uiForm, uiTable, dicTable, uiActions, disabled } = option
  const { columns, edit_render, default_value_parse } = uiTable
  const renderMethod = default_value_parse.renderMethod || 'editRender'
  const storageColumns = getGridColumns(uiTable)
  const items = option.uiForm?.items || []

  const state: TypedAny<SelectOptionType[]> = {}

  if (edit_render && uiForm) {
    const params = option.params || {}
    const renderComponents = items.filter((f) =>
      edit_render_components.includes(f.elComponent || '')
    )
    await onComponentServerFetch(renderComponents, state, params, {})
    await onInitApiData(renderComponents, state, params, {})
  }

  const cols: BusinessUIColumnType[] =
    columns.map((column) => {
      const defaultProps = column.set_json_parse.props || {}
      const component = column.set_json_parse.component || ''
      const prefix = column.set_json_parse.prefix || ''
      const suffix = column.set_json_parse.suffix || ''
      for (const key in defaultProps) {
        const value = defaultProps[key]
        if (value === 'true' || value === 'false') {
          defaultProps[key] = value === 'true'
        }
      }
      const isVxeType = ['checkbox'].includes(defaultProps.type)
      const option: any = {
        ...defaultProps,
        field: defaultProps.type === 'action' ? defaultProps.type : column.field,
        title: isVxeType ? '' : column.title || column.field,
        params: column
      }

      // 行内编辑
      if (edit_render && uiForm && !disabled) {
        const form = uiForm.items.find(
          (f) => f.field === option.field || f.rel_item === option.field
        )
        const elComponent = form?.elComponent || ''
        const elComponentKey = elToVxeComponent(elComponent)
        if (form && edit_render_components.includes(elComponent)) {
          option.field = form.field

          const name = toNameCapitalize(elComponentKey)

          const props = getBusinessBind(form, elComponentKey)

          if (props.type === 'textarea') {
            props.type = 'text'
          }

          props.transfer = true

          if (props.multiple) {
            props.collapseTags = true
          }

          if (form.required) {
            props.required = true
          }

          const getOptions = () => {
            return (
              state[option.field] || state[form.component] || getDicOptions(form, dicTable || [])
            )
          }

          const renderMethodOption: VxeColumnPropTypes.EditRender = {
            name,
            props: {},
            options: [],
            events: {
              change({ row, column }: any, value: any) {
                if (form.rel_item) {
                  const options1 = column[renderMethod].props?.options || []
                  const options2 = column[renderMethod].options || []
                  const item = findTree([...options1, ...options2], (f) => f.value === value)
                  if (item && item.item) {
                    row[form.rel_item] = item.item.label
                  }
                }
              }
            }
          }

          if (['el-tree-select', 'el-cascader'].includes(elComponentKey)) {
            props.options = getOptions()
          } else {
            renderMethodOption.options = getOptions()
          }

          if (!['vxe-date-picker'].includes(elComponentKey)) renderMethodOption.props = props

          option[renderMethod] = renderMethodOption

          if (!option[renderMethod].options || !option[renderMethod].options.length) {
            option.formatter = ({ row }: { row: TypedAny }) => {
              return row[column.field]
            }
          }
        }
      }

      // 恢复用户自定义的列宽，排序，固定，等等配置
      const storageColumn = storageColumns.find((f) => f.field === option.field)
      if (storageColumn) assign(option, storageColumn)

      // 前缀/后缀
      if (!option.formatter && (prefix || suffix)) {
        option.formatter = ({ row }: { row: TypedAny }) => {
          if (row[column.field]) {
            return `${prefix}${row[column.field]}${suffix}`
          } else {
            return ''
          }
        }
      }

      if (column.is_sort_col) {
        option['sortable'] = column.is_sort_col
      }
      if (column.set_json_parse.nodeApp) {
        option.slots = {
          default: 'wf_node'
        }
      } else if (component === 'el-tag' && formatRowComponents.some((s) => s.value === component)) {
        option.slots = {
          default: 'el_tag'
        }
      }
      return option
    }) || []
  if (storageColumns.length) {
    cols.sort((a, b) => {
      return (a.seq || 0) - (b.seq || 0)
    })
  }
  if (uiActions) initGridActions({ cols, uiActions, storageColumns })

  return cols
}

/**
 * 保存列配置
 */
export const setGridColumns = (uiTable: BusinessUITableType, columns: TypedAny[]) => {
  Local.set(`${uiTable.id}_columns`, columns)
  return columns
}

/**
 * 获取保存的列配置
 */
export const getGridColumns = (uiTable: BusinessUITableType): TypedAny[] => {
  return Local.get(`${uiTable.id}_columns`) || []
}

/**
 * 恢复列配置
 */
export const removeGridColumns = (uiTable: BusinessUITableType) => {
  Local.remove(`${uiTable.id}_columns`)
}

/**
 * 格式化表配置
 * @param option
 */
export const initGridProps = (option: {
  uiTable: BusinessUITableType
  uiForm?: BusinessUIFormType
  filename?: string
  exportConfig?: VxeTablePropTypes.ExportConfig
  radioConfig?: VxeTablePropTypes.RadioConfig
  disabled?: boolean
}) => {
  const { uiTable, filename, exportConfig, disabled } = option
  const { default_value_parse, edit_render, pagination, columns } = uiTable
  const keyField = default_value_parse.keyField || 'id'
  const gridProps: VxeGridProps = {
    columns: [],
    printConfig: {},
    exportConfig: {
      ...exportConfig,
      modes: pagination ? ['current', 'selected', 'all'] : ['current', 'selected'],
      filename: t(filename || 'filename'),
      sheetName: t(filename || 'filename'),
      sheetMethod: ({ worksheet }: any) => {
        const primary = themeConfig.value.primary.replace('#', '')
        const row = worksheet.getRow(1)
        if (row) {
          row.font = { bold: true, color: { argb: 'ffffff' } }
          row.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: primary } }
        }
      }
    },
    rowConfig: {
      keyField,
      isHover: true,
      isCurrent: true
    },
    columnConfig: {
      resizable: true
    },
    showOverflow: true,
    showHeaderOverflow: true,
    showFooterOverflow: true
  }

  const fields = columns.filter((f) => f.set_json_parse.merge).map((v) => v.field)
  if (fields.length) {
    // 通用行合并函数（将相同多列数据合并为一行）
    gridProps['spanMethod'] = ({ row, _rowIndex, column, visibleData }) => {
      const cellValue = row[column.field]
      if (cellValue && fields.includes(column.field)) {
        const prevRow = visibleData[_rowIndex - 1]
        let nextRow = visibleData[_rowIndex + 1]
        if (prevRow && prevRow[column.field] === cellValue) {
          return { rowspan: 0, colspan: 0 }
        } else {
          let countRowspan = 1
          while (nextRow && nextRow[column.field] === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex]
          }
          if (countRowspan > 1) {
            return { rowspan: countRowspan, colspan: 1 }
          }
        }
      }
    }
  }

  // if (!pagination) {
  //   gridProps.scrollY = {
  //     enabled: true,
  //     gt: 0
  //   }
  // }

  // 配置单选
  const radio = columns.find((f) => f.set_json_parse.props.type === 'radio')
  if (radio) {
    gridProps.radioConfig = {
      trigger: 'row',
      reserve: true,
      highlight: true
    }
    const checkStrictly = !radio.set_json_parse.props.checkStrictly
    if (radio.field.indexOf('empty_') === -1) {
      gridProps.radioConfig.labelField = radio.field
    }
    if (checkStrictly) {
      gridProps.radioConfig.visibleMethod = ({ row }) => {
        const children = row.children || []
        return !children.length
      }
      // gridProps.radioConfig.checkMethod = ({row}) => {
      //   const children = row.children || []
      //   return !children.length
      // }
    }
  }

  if (option.radioConfig) gridProps.radioConfig = option.radioConfig

  // 配置多选
  const checkbox = columns.find((f) => f.set_json_parse.props.type === 'checkbox')
  if (checkbox) {
    gridProps.checkboxConfig = {
      reserve: true,
      checkStrictly: !!checkbox.set_json_parse.props.checkStrictly
    }
    if (checkbox.field.indexOf('empty_') === -1) {
      gridProps.checkboxConfig.labelField = checkbox.field
    }
  }

  // 编辑
  if (edit_render && !disabled) {
    gridProps.editConfig = {
      trigger: 'click',
      // trigger: 'dblclick',
      mode: 'row',
      showStatus: true
    }
    gridProps.keepSource = true
    if (option.uiForm) {
      const rules = option.uiForm.items.filter((f) => f.required)

      const editRules: VxeTablePropTypes.EditRules<TypedAny> = {}

      rules.forEach((r) => {
        editRules[r.field] = [{ required: true, validator: 'ValidValue' }]
      })

      gridProps.editRules = editRules
    }
  }

  // 树节点
  const treeCol = columns.find((s) => s.is_pid)
  if (treeCol) {
    gridProps.treeConfig = {
      transform: false,
      expandAll: treeCol.set_json_parse.expandAll || false,
      rowField: keyField,
      parentField: treeCol.field
    }
  } else {
    gridProps.stripe = true
  }

  // 默认排序方式
  const orderCol = columns.find((s) => s.is_sort_col && s.orderby)
  if (orderCol) {
    gridProps.sortConfig = {
      defaultSort: {
        field: orderCol.field,
        order: orderCol.orderby || null // asc（升序）,desc（降序）, null
      }
    }
  }

  // if (default_value_parse.toolbarConfig) gridProps.toolbarConfig = default_value_parse.toolbarConfig

  return gridProps
}

// 已废弃的格式化
const discard = [
  'money-accounting',
  'money-accounting-not',
  'money-zhy',
  'money-zhy-not',
  'money-zh',
  'money-zh-not'
]

/**
 * 初始化表尾合计
 * @param gridProps
 * @param columns
 */
export const initFooterMethod = (gridProps: VxeGridProps, columns: BusinessUIColumnType[]) => {
  // 表尾合计
  const showFooter = columns.some((s) => s.params?.set_json_parse.showFooter)
  if (showFooter) {
    const moneyKeys = formatOptions.filter((f) => f.type === 'number').map((v) => v.value)
    gridProps.showFooter = showFooter
    const sumColumns = columns.filter((f) => f.params?.set_json_parse.showFooter)
    // const keys = sumColumns.map(v => v.field)
    const footerMethod: VxeTablePropTypes.FooterMethod<TypedAny> = ({ columns, data }) => {
      return [
        columns.map((column, columnIndex) => {
          if (columnIndex === 0) {
            return '合计'
          }
          const col = findTree(sumColumns, (f) => f.field === column.field)
          if (col && col.item) {
            const formatType = col.item.params?.set_json_parse.formatType
            const prefix = col.item.params?.set_json_parse.prefix || ''
            const suffix = col.item.params?.set_json_parse.suffix || ''
            if (formatType && moneyKeys.includes(formatType)) {
              let amount = 0
              eachTree(data, (v) => {
                if (discard.includes(formatType)) {
                  const value = (v[column.field] || '').replace(/[,¥元]/g, '')
                  const num = Number(value) || 0
                  amount = add(num, amount)
                } else {
                  const num = Number(v[column.field]) || 0
                  amount = add(num, amount)
                }
              })
              return `${prefix}${getFormatOptions(col.item.params, amount)}${suffix}`
            } else {
              return `${prefix}${sum(data, column.field)}${suffix}`
            }
          }
          return null
        })
      ]
    }
    gridProps.footerRowClassName = 'bg-danger-light'
    gridProps.footerMethod = footerMethod
  }
}

/**
 * 格式化表格操作按钮
 * @param cols
 * @param uiActions
 * @param storageColumns
 */
export const initGridActions = ({
  cols,
  uiActions,
  storageColumns
}: {
  cols: any[]
  uiActions: BusinessUIAction[]
  storageColumns: TypedAny[]
}) => {
  // const globalActions = uiActions.filter(f => f.global)
  const notGlobalActions = uiActions.filter((f) => !f.global)
  if (notGlobalActions.length) {
    const colAction = cols.find((f) => f.type === 'action')
    if (colAction) {
      delete colAction.type
      colAction['slots'] = { default: 'action' }
      colAction.field = colAction.type
    } else {
      const fontWidth = sum(
        notGlobalActions
          .filter((f) => f.action !== 'can_submit')
          .map((v) => v.name.length * 12 + 23)
      )
      // if (wf_design && uiActions.some(s => s.action === 'can_submit')) count -= 2
      const action = storageColumns.find((f) => f.field === 'action')
      cols.push({
        field: 'action',
        title: '操作',
        showOverflow: false,
        width: action ? action.width : fontWidth,
        fixed: action
          ? action.fixed
          : document.body.clientWidth > 800
            ? cols.length >= 7
              ? 'right'
              : ''
            : '',
        slots: { default: 'action' }
      })
    }
  }
  return uiActions
}

/**
 * 表格格式化字典
 * @param rows
 * @param cols
 * @param dicTable
 * @param uiForm
 */
export const formatColRows = ({
  rows,
  dicTable,
  uiTable,
  uiForm,
  isDeleteNull
}: {
  rows: TypedAny[]
  dicTable?: DicType[]
  uiTable?: BusinessUITableType
  uiForm?: BusinessUIFormType
  isDeleteNull?: boolean
}) => {
  const columns = uiTable?.columns || []
  const items = uiForm?.items || []
  const edit_render = uiTable?.edit_render
  const disabledKeys = edit_render ? items.map((v) => v.field || v.rel_item) : []
  rows.forEach((row) => {
    const oldRow = clone(row, true)
    columns.forEach((col) => {
      const value = oldRow[col.field]
      // 其他
      const formatType = col.set_json_parse?.formatType
      if (formatType) {
        row[col.field] = getFormatOptions(col, value)
      }
      if (col.set_json_parse.nodeApp) {
        const status: string = getNotEmpty(row, ['wf_stauts', 'status'])
        row[`${col.field}_display_type`] = getNotEmpty(wfStatusTypes, [status], 'primary')
      }
      // 删除null 不然表格全量导出时会被转成‘null’字符串
      if (isDeleteNull && row[col.field] === null) row[col.field] = ''
    })
    if (uiForm) {
      uiForm.items.forEach((col) => {
        const value = oldRow[col.field]
        // 其他
        const formatType = col.set_json_parse.formatType
        if (formatType) {
          row[col.field] = getFormatOptions(col, value)
        }
      })
    }
    if (dicTable?.length) formatDicTable(row, dicTable, disabledKeys)
  })
}

/**
 * vxe-table表格导出过滤
 * @param param0
 * @returns
 */
export const columnFilterMethod = ({ column }: { column: VxeTableDefines.ColumnInfo }) => {
  return (
    !['seq', 'index', 'checkbox'].includes(column.type || '') && !['action'].includes(column.field)
  )
}
